package hypernexusnats

import (
	"encoding/json"
	"fmt"
	"reflect"
	"sync"

	"github.com/nats-io/nats.go"
)

// Subscriber 提供NATS消息订阅功能
type Subscriber struct {
	client        *NatsClient
	handlers      map[string][]MessageHandler
	mu            sync.RWMutex
	subscriptions map[string]*nats.Subscription
}

// MessageHandler 消息处理器接口
type MessageHandler interface {
	Handle(msg *Message) error
}

// MessageHandlerFunc 函数类型的消息处理器
type MessageHandlerFunc func(msg *Message) error

// Handle 实现MessageHandler接口
func (f MessageHandlerFunc) Handle(msg *Message) error {
	return f(msg)
}

// NewSubscriber 创建一个新的Subscriber实例
func NewSubscriber(client *NatsClient) *Subscriber {
	return &Subscriber{
		client:        client,
		handlers:      make(map[string][]MessageHandler),
		subscriptions: make(map[string]*nats.Subscription),
	}
}

// Subscribe 订阅主题
func (s *Subscriber) Subscribe(topic string, handler MessageHandler) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	// 检查客户端是否初始化
	if s.client == nil {
		return fmt.Errorf("NATS客户端未初始化")
	}

	// 添加处理器
	if _, exists := s.handlers[topic]; !exists {
		s.handlers[topic] = []MessageHandler{}

		// 创建NATS订阅
		sub, err := s.client.Conn.Subscribe(topic, func(msg *nats.Msg) {
			s.handleMessage(topic, msg)
		})
		if err != nil {
			return fmt.Errorf("订阅主题失败: %v", err)
		}

		// 保存订阅
		s.subscriptions[topic] = sub
	}

	// 添加处理器到列表
	s.handlers[topic] = append(s.handlers[topic], handler)
	return nil
}

// SubscribeFunc 使用函数订阅主题
func (s *Subscriber) SubscribeFunc(topic string, handlerFunc func(msg *Message) error) error {
	return s.Subscribe(topic, MessageHandlerFunc(handlerFunc))
}

// QueueSubscribe 队列订阅主题
func (s *Subscriber) QueueSubscribe(topic, queue string, handler MessageHandler) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	// 检查客户端是否初始化
	if s.client == nil {
		return fmt.Errorf("NATS客户端未初始化")
	}

	// 生成唯一的订阅标识符
	subID := fmt.Sprintf("%s:%s", topic, queue)

	// 添加处理器
	if _, exists := s.handlers[subID]; !exists {
		s.handlers[subID] = []MessageHandler{}

		// 创建NATS队列订阅
		sub, err := s.client.Conn.QueueSubscribe(topic, queue, func(msg *nats.Msg) {
			s.handleMessage(subID, msg)
		})
		if err != nil {
			return fmt.Errorf("队列订阅主题失败: %v", err)
		}

		// 保存订阅
		s.subscriptions[subID] = sub
	}

	// 添加处理器到列表
	s.handlers[subID] = append(s.handlers[subID], handler)
	return nil
}

// QueueSubscribeFunc 使用函数进行队列订阅
func (s *Subscriber) QueueSubscribeFunc(topic, queue string, handlerFunc func(msg *Message) error) error {
	return s.QueueSubscribe(topic, queue, MessageHandlerFunc(handlerFunc))
}

// Unsubscribe 取消订阅
func (s *Subscriber) Unsubscribe(topic string) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	// 检查是否已订阅
	if _, exists := s.handlers[topic]; !exists {
		return fmt.Errorf("未订阅主题: %s", topic)
	}

	// 取消NATS订阅
	if sub, exists := s.subscriptions[topic]; exists {
		err := sub.Unsubscribe()
		if err != nil {
			return fmt.Errorf("取消订阅失败: %v", err)
		}
		delete(s.subscriptions, topic)
	}

	// 删除处理器
	delete(s.handlers, topic)
	return nil
}

// SubscribeJSON 订阅JSON消息并自动解析到指定类型
func (s *Subscriber) SubscribeJSON(topic string, targetType interface{}, handler func(data interface{}) error) error {
	// 获取目标类型
	targetValue := reflect.ValueOf(targetType)
	if targetValue.Kind() != reflect.Ptr {
		return fmt.Errorf("targetType必须是指针类型")
	}

	// 创建处理函数
	return s.SubscribeFunc(topic, func(msg *Message) error {
		// 创建目标类型的新实例
		newInstance := reflect.New(targetValue.Elem().Type()).Interface()

		// 将消息数据解析为JSON
		jsonData, err := json.Marshal(msg.Data)
		if err != nil {
			return fmt.Errorf("JSON编码失败: %v", err)
		}

		// 解析JSON到目标类型
		err = json.Unmarshal(jsonData, newInstance)
		if err != nil {
			return fmt.Errorf("JSON解码失败: %v", err)
		}

		// 调用处理函数
		return handler(newInstance)
	})
}

// 处理接收到的消息
func (s *Subscriber) handleMessage(topic string, msg *nats.Msg) {
	s.mu.RLock()
	handlers, exists := s.handlers[topic]
	s.mu.RUnlock()

	if !exists || len(handlers) == 0 {
		return
	}

	// 解析消息
	var message Message
	err := json.Unmarshal(msg.Data, &message)
	if err != nil {
		// 如果不是标准格式的消息，创建一个简单的消息对象
		message = Message{
			Topic: topic,
			Data:  msg.Data,
		}
	}

	// 调用所有处理器
	for _, handler := range handlers {
		// 使用goroutine异步处理消息
		go func(h MessageHandler, m *Message) {
			err := h.Handle(m)
			if err != nil {
				fmt.Printf("处理消息失败: %v\n", err)
			}
		}(handler, &message)
	}
}
